package com.atguigu.tingshu.common.minio.service.impl;

import com.atguigu.tingshu.common.minio.config.MinioProperties;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.minio.service.FileUploadService;
import com.atguigu.tingshu.common.util.MD5;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.StatObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

/**
 * <a href="https://www.shallowrecall.top/">Recall`Blog</a></br>
 * <a href="https://github.com/ShallowRecall">GitHub</a>
 *
 * @author Recall
 * @createTime 2025/03/13 21:02
 **/
@Slf4j
public class FileUploadServiceImpl implements FileUploadService {

    @Autowired
    private MinioProperties minioProperties;

    @Autowired
    private MinioClient minioClient;

    @Override
    public String fileUploadService(MultipartFile file) {
        // 对不同名但是内容相同的文件进行去重
        String originalFilename = file.getOriginalFilename();
        String objectKey = null;
        try {
            byte[] bytes = file.getBytes();
            String s = new String(bytes);
            String preFix = MD5.encrypt(s);
            String suffix = originalFilename.substring(originalFilename.lastIndexOf("."), originalFilename.length());
            objectKey = preFix + suffix;

            // 检查上传的文件桶中是否存在（抛出异常则不存在）
            StatObjectArgs.Builder builder = StatObjectArgs.builder();
            StatObjectArgs statObjectArgs = builder
                    .bucket(minioProperties.getBucketName())
                    .object(objectKey)
                    .build();

            minioClient.statObject(statObjectArgs);
            // 桶中存在，直接返回桶中地址
            return minioProperties.getEndpointUrl() + "/" + minioProperties.getBucketName() + "/" + objectKey;
        } catch (IOException e) {
            log.error("文件转字节失败：{}", e.getMessage());
            throw new GuiguException(201, "文件转字节失败");
        } catch (Exception e) {
            // 桶中不存在，则上传到桶中
            log.info("该文件在桶中不存在，可以上传到minio中");
            try {
                // 将文件上传到桶中
                PutObjectArgs.Builder putObjectArgsBuilder = PutObjectArgs.builder();
                PutObjectArgs putObjectArgs = putObjectArgsBuilder
                        .bucket(minioProperties.getBucketName())
                        .object(objectKey)
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .build();
                minioClient.putObject(putObjectArgs);
                log.info("文件上传成功");
                // 将图片地址返回
                return minioProperties.getEndpointUrl() + "/" + minioProperties.getBucketName() + "/" + objectKey;
            } catch (Exception ex) {
                log.error("上传文件到minio中失败：{}", ex.getMessage());
                throw new GuiguException(201, "上传文件到minio中失败");
            }
        }
    }
}
